#include "server.h"
#include "mongoose.h"

#if !defined(LISTENING_PORT)
#define LISTENING_PORT	"23456"
#endif /* !LISTENING_PORT */
/*
static const char *standard_reply =	"HTTP/1.1 200 OK\r\n"
                                    "Content-Type: text/plain\r\n"
                                    "Connection: close\r\n\r\n";
*/
void
print_hex(char *buffer, int size);
/*
static void
test_put(struct mg_connection *conn, const struct mg_request_info *ri,
         void *user_data)
{
    mg_printf(conn, "%s", standard_reply);
    mg_write(conn, ri->post_data, ri->post_data_len);
}*/

static void
http_get_users(struct mg_connection *conn, const struct mg_request_info *ri,
               void *user_data)
{
    struct table_chain *table;
    int n = 0;
    char reply[1400] = {0};
    char *r;


    pthread_mutex_lock(&tablemutex);
	//MLog("Lock: get user");
    for (table = acct_table_header; table; table = table->next)
    {
        if (table->table->status == USER_ACCOUNTING)
        {
            n++;
            r = strrchr(reply, ';');
            r = r ? (r + 1) : reply;
            sprintf(r, "%s,%s,%ld,%d,%d,%d,%d;", table->table->name, table->table->ipaddr, table->table->login_time, table->table->instant_up_rate,
                    table->table->instant_down_rate, table->table->total_up_traffic, table->table->total_down_traffic);
            if (strlen(reply) > 1000)
            {
                mg_write(conn, reply, strlen(reply));
                memset(reply, 0, sizeof(reply));
            }
        }
    }
    if (strlen(reply))
    {
        mg_write(conn, reply, strlen(reply));
        memset(reply, 0, sizeof(reply));
    }
    if (n == 0)
    {
        mg_write(conn, "\"", 2);
    }
    pthread_mutex_unlock(&tablemutex);
	//MLog("UnLock: get user");
}

static void
http_set_rate(struct mg_connection *conn, const struct mg_request_info *ri,
              void *user_data)
{
    char *name, *download, *upload, *sessionid = 0;
    struct table_chain *table;
    int n = 0;
    int checkname, checkid;
    char reply[100] = {0};

    name = mg_get_var(conn, "username");
    download = mg_get_var(conn, "download");
    upload = mg_get_var(conn, "upload");

    if (name == 0)
    {
        sprintf(reply, "failed");
        mg_write(conn, reply, strlen(reply));
        return ;
    }
    else
    {
        Vdebug(DEBUG_DATE, "[http if]set rate: down %s, up %s", download, upload);
    }
    if ((download == 0) && (upload == 0))
    {
        sprintf(reply, "failed");
        mg_write(conn, reply, strlen(reply));
        return ;
    }

    checkname = 1;
    checkid = 0;

    if ((!checkname) && (!checkid))
    {
        return ;
    }
    pthread_mutex_lock(&tablemutex);
    for (table = acct_table_header; table; table = table->next)
    {
        //assert(table->table);
        if (((checkname && strncmp(table->table->name, name, MAX(strlen(table->table->name), strlen(name)))) == 0)
                && ((checkid && strncmp(table->table->session_tx, sessionid, MAX(strlen(table->table->session_tx), strlen(sessionid)))) == 0))
        {
            if (table->table->status == USER_ACCOUNTING)
            {
                table->table->set_download_rate = atoi(download);
                table->table->set_upload_rate = atoi(upload);
                n++;
            }
        }
    }
    pthread_mutex_unlock(&tablemutex);
    if (n == 0)
    {
        sprintf(reply, "failed");
        mg_write(conn, reply, strlen(reply));
    }
    else
    {
        sprintf(reply, "okokok");
        mg_write(conn, reply, strlen(reply));
    }
}

static void
http_kick_user(struct mg_connection *conn, const struct mg_request_info *ri,
               void *user_data)
{
    char *name, *message, *kick_time, *sessionid = 0;
    struct table_chain *table;
    int n = 0;
    int checkname, checkid;
    unsigned int message_length = 0;
    char reply[100] = {0};

    name = mg_get_var(conn, "username");
    message = mg_get_var(conn, "message");
    kick_time = mg_get_var(conn, "time");

    if (name == 0)
    {
        sprintf(reply, "failed");
        mg_write(conn, reply, strlen(reply));
        return ;
    }
    else
    {
        Vdebug(DEBUG_DATE, "[http if]kick user: %s", name);
    }
    if (message)
    {
        message_length = strlen(message);
        Vdebug(DEBUG_DATE, "[http if]kick message: %s", message);
    }

    checkname = 1;
    checkid = 0;

    if ((!checkname) && (!checkid))
    {
        return ;
    }
    pthread_mutex_lock(&tablemutex);
	//MLog("Lock: kick user");
    for (table = acct_table_header; table; table = table->next)
    {
        //assert(table->table);
        if (((checkname && strncmp(table->table->name, name, MAX(strlen(table->table->name), strlen(name)))) == 0)
                && ((checkid && strncmp(table->table->session_tx, sessionid, MAX(strlen(table->table->session_tx), strlen(sessionid)))) == 0))
        {
            if (table->table->status == USER_ACCOUNTING)
            {
                table->table->update_time = time(NULL);
                table->table->status = USER_KICKOFF;
				if (kick_time) {
					table->table->kick_time = atoi(kick_time);
					Vdebug(DEBUG_DATE, "[http if]kick time %u", table->table->kick_time);
				}
                if (message_length > 0)
                {
                    table->table->set_message_length = message_length;
                    memcpy(table->table->set_message, message, message_length);
                }
                rad_account_packet_send(table, ACCT_STOP, "Admin-Reset", NULL);
                n++;
            }
        }
    }
    pthread_mutex_unlock(&tablemutex);
	//MLog("UnLock: kick user");
    if (n == 0)
    {
        sprintf(reply, "failed");
        mg_write(conn, reply, strlen(reply));
    }
    else
    {
        sprintf(reply, "okokok");
        mg_write(conn, reply, strlen(reply));
    }
}

static void
http_send_message(struct mg_connection *conn, const struct mg_request_info *ri,
                  void *user_data)
{
    char *name, *message, *sessionid = 0;
    struct table_chain *table;
    int n = 0;
    int checkname, checkid;
    unsigned int message_length = 0;
    char reply[100] = {0};

    name = mg_get_var(conn, "username");
    message = mg_get_var(conn, "message");

    if (name == 0)
    {
        sprintf(reply, "failed");
        mg_write(conn, reply, strlen(reply));
        return ;
    }
    if (!message)
    {
        sprintf(reply, "failed");
        mg_write(conn, reply, strlen(reply));
        return ;
    }

    message_length = strlen(message);
    Vdebug(DEBUG_DATE, "[http if]send message: %s to %s", message, name);
    print_hex(message, message_length);    

    checkname = 1;
    checkid = 0;

    if ((!checkname) && (!checkid))
    {
        return ;
    }
    pthread_mutex_lock(&tablemutex);
    for (table = acct_table_header; table; table = table->next)
    {
        //assert(table->table);
        if (((checkname && strncmp(table->table->name, name, MAX(strlen(table->table->name), strlen(name)))) == 0)
                && ((checkid && strncmp(table->table->session_tx, sessionid, MAX(strlen(table->table->session_tx), strlen(sessionid)))) == 0))
        {
            if (table->table->status == USER_ACCOUNTING)
            {
                table->table->set_message_length = message_length;
                memcpy(table->table->set_message, message, message_length);
                n++;
            }
        }
    }
    pthread_mutex_unlock(&tablemutex);
    if (n == 0)
    {
        sprintf(reply, "failed");
        mg_write(conn, reply, strlen(reply));
    }
    else
    {
        sprintf(reply, "okokok");
        mg_write(conn, reply, strlen(reply));
    }
}

int start_http(void)
{
    // int			user_data = 1234;
    struct mg_context	*ctx;

    ctx = mg_start();
    mg_set_option(ctx, "ports", LISTENING_PORT);

    mg_set_uri_callback(ctx, "/get_users", &http_get_users, NULL);
    mg_set_uri_callback(ctx, "/kick_user", &http_kick_user, NULL);
    mg_set_uri_callback(ctx, "/send_message", &http_send_message, NULL);
    mg_set_uri_callback(ctx, "/set_rate", &http_set_rate, NULL);
    /*	mg_set_uri_callback(ctx, "/test_get_var", &test_get_var, NULL);
    	mg_set_uri_callback(ctx, "/test_get_request_info", &test_get_ri, NULL);
    	mg_set_uri_callback(ctx, "/foo/", &test_get_ri, NULL);
    	mg_set_uri_callback(ctx, "/test_user_data",
    			&test_user_data, &user_data);
    	mg_set_uri_callback(ctx, "/p", &test_post, NULL);
    	mg_set_uri_callback(ctx, "/put", &test_put, NULL);
    	mg_set_uri_callback(ctx, "/test_remove_callback",
    			&test_remove_callback, ctx);

    	mg_set_error_callback(ctx, 404, &test_error, NULL);
    	mg_set_error_callback(ctx, 0, &test_error, NULL);

    	mg_set_auth_callback(ctx, "/foo/secret", &test_protect, (void *) "joe");*/
    return 0;
}
